<template>
<div class="parent">
    <div id="container"></div>
    <div id="controls"></div>
</div>
</template>

<script setup lang="ts">
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import {GUI} from 'three/examples/jsm/libs/lil-gui.module.min.js'

import { onMounted } from 'vue';

onMounted(()=>{
    const scene = new THREE.Scene();
    // scene.background = new THREE.Color('black');
    const fov = 45;
	const aspect = 2; // the canvas default
	const near = 0.1;
	const far = 100;
    const camera = new THREE.PerspectiveCamera(fov,aspect,near,far);
    camera.position.set( 0, 10, 20 );
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.getElementById('container')?.appendChild(renderer.domElement);

    const controls = new OrbitControls(camera, renderer.domElement);
    controls.target.set(0, 5, 0);
    controls.update();

    {//添加地面
        const planeSize = 40;
        const loader = new THREE.TextureLoader();
        const texture = loader.load('/pngs/checker.png');
        texture.wrapS = THREE.RepeatWrapping;
        texture.wrapT = THREE.RepeatWrapping;
        texture.magFilter = THREE.NearestFilter;
        texture.colorSpace = THREE.SRGBColorSpace;
        const repeats = planeSize / 2;
        texture.repeat.set(repeats, repeats);

        const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
        const planeMat = new THREE.MeshBasicMaterial({
            map: texture,
            side: THREE.DoubleSide,
        });
        const mesh = new THREE.Mesh(planeGeo, planeMat);
        mesh.rotation.x = Math.PI * -.5;
        scene.add(mesh);
    }

    {//立方体，材质响应光照
        const cubeSize = 4;
        const cubeGeo = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
        const cubeMat = new THREE.MeshPhongMaterial({ color: '#8AC' });
        const mesh = new THREE.Mesh(cubeGeo, cubeMat);
        mesh.position.set(cubeSize + 1, cubeSize / 2, 0);
        scene.add(mesh);
    }

    {//球体
        const sphereRadius = 4;
        const sphereWidthDivisions = 32;
        const sphereHeightDivisions = 16;
        const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
        const sphereMat = new THREE.MeshPhongMaterial({ color: '#CA8' });
        const mesh = new THREE.Mesh(sphereGeo, sphereMat);
        mesh.position.set(-sphereRadius - 1, sphereRadius+2,0);
        scene.add(mesh);
    }

    class ColorGUIHelper{
        private object: any;
        private prop: any;
        constructor(object:any, prop:any){
            this.object = object;
            this.prop = prop;
        }

        get value() {
            return `#${this.object[ this.prop ].getHexString()}`;
        }

        set value(hexString:any) {
            this.object[ this.prop ].set(hexString);
        }
    }

    {
        const color = 0xFFFFFF;
        const intensity = 1;
        const light = new THREE.AmbientLight(color, intensity);
        scene.add(light);

        const gui = new GUI({container:document.getElementById('controls')!!});
        gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
        gui.add(light, 'intensity', 0, 5, 0.01);
    }


    const render = () => {
        const canvas = renderer.domElement;
        const width = canvas.clientWidth;
        const height = canvas.clientHeight;
        const needResize = canvas.width !== width || canvas.height !== height;
        if (needResize) {
            renderer.setSize(width, height, false);
            camera.aspect = width / height;
            camera.updateProjectionMatrix();
        }
        renderer.render(scene, camera);
        requestAnimationFrame(render);
    };
    requestAnimationFrame(render);

})

</script>

<style scoped>
.parent {
    position: relative;
    width: 100%;
    height: 100%;
}
.parent > * {
    position: absolute;
}
#controls{
    right: 0;
}
</style>